home *** CD-ROM | disk | FTP | other *** search
/ American Osteopathic Ass…tion Yearbook 2005 & 2006 / American Osteopathic Association Yearbook 2005 & 2006.iso / mac / app / random.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2004-07-22  |  26.1 KB  |  678 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.3)
  3.  
  4. '''Random variable generators.
  5.  
  6.     integers
  7.     --------
  8.            uniform within range
  9.  
  10.     sequences
  11.     ---------
  12.            pick random element
  13.            pick random sample
  14.            generate random permutation
  15.  
  16.     distributions on the real line:
  17.     ------------------------------
  18.            uniform
  19.            normal (Gaussian)
  20.            lognormal
  21.            negative exponential
  22.            gamma
  23.            beta
  24.            pareto
  25.            Weibull
  26.  
  27.     distributions on the circle (angles 0 to 2pi)
  28.     ---------------------------------------------
  29.            circular uniform
  30.            von Mises
  31.  
  32. General notes on the underlying Mersenne Twister core generator:
  33.  
  34. * The period is 2**19937-1.
  35. * It is one of the most extensively tested generators in existence
  36. * Without a direct way to compute N steps forward, the
  37.   semantics of jumpahead(n) are weakened to simply jump
  38.   to another distant state and rely on the large period
  39.   to avoid overlapping sequences.
  40. * The random() method is implemented in C, executes in
  41.   a single Python step, and is, therefore, threadsafe.
  42.  
  43. '''
  44. from math import log as _log, exp as _exp, pi as _pi, e as _e
  45. from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
  46. from math import floor as _floor
  47. __all__ = [
  48.     'Random',
  49.     'seed',
  50.     'random',
  51.     'uniform',
  52.     'randint',
  53.     'choice',
  54.     'sample',
  55.     'randrange',
  56.     'shuffle',
  57.     'normalvariate',
  58.     'lognormvariate',
  59.     'cunifvariate',
  60.     'expovariate',
  61.     'vonmisesvariate',
  62.     'gammavariate',
  63.     'stdgamma',
  64.     'gauss',
  65.     'betavariate',
  66.     'paretovariate',
  67.     'weibullvariate',
  68.     'getstate',
  69.     'setstate',
  70.     'jumpahead']
  71. NV_MAGICCONST = 4 * _exp(-0.5) / _sqrt(2.0)
  72. TWOPI = 2.0 * _pi
  73. LOG4 = _log(4.0)
  74. SG_MAGICCONST = 1.0 + _log(4.5)
  75. import _random
  76.  
  77. class Random(_random.Random):
  78.     """Random number generator base class used by bound module functions.
  79.  
  80.     Used to instantiate instances of Random to get generators that don't
  81.     share state.  Especially useful for multi-threaded programs, creating
  82.     a different instance of Random for each thread, and using the jumpahead()
  83.     method to ensure that the generated sequences seen by each thread don't
  84.     overlap.
  85.  
  86.     Class Random can also be subclassed if you want to use a different basic
  87.     generator of your own devising: in that case, override the following
  88.     methods:  random(), seed(), getstate(), setstate() and jumpahead().
  89.  
  90.     """
  91.     VERSION = 2
  92.     
  93.     def __init__(self, x = None):
  94.         '''Initialize an instance.
  95.  
  96.         Optional argument x controls seeding, as for Random.seed().
  97.         '''
  98.         self.seed(x)
  99.         self.gauss_next = None
  100.  
  101.     
  102.     def seed(self, a = None):
  103.         '''Initialize internal state from hashable object.
  104.  
  105.         None or no argument seeds from current time.
  106.  
  107.         If a is not None or an int or long, hash(a) is used instead.
  108.         '''
  109.         super(Random, self).seed(a)
  110.         self.gauss_next = None
  111.  
  112.     
  113.     def getstate(self):
  114.         '''Return internal state; can be passed to setstate() later.'''
  115.         return (self.VERSION, super(Random, self).getstate(), self.gauss_next)
  116.  
  117.     
  118.     def setstate(self, state):
  119.         '''Restore internal state from object returned by getstate().'''
  120.         version = state[0]
  121.         if version == 2:
  122.             (version, internalstate, self.gauss_next) = state
  123.             super(Random, self).setstate(internalstate)
  124.         else:
  125.             raise ValueError('state with version %s passed to Random.setstate() of version %s' % (version, self.VERSION))
  126.  
  127.     
  128.     def __getstate__(self):
  129.         return self.getstate()
  130.  
  131.     
  132.     def __setstate__(self, state):
  133.         self.setstate(state)
  134.  
  135.     
  136.     def __reduce__(self):
  137.         return (self.__class__, (), self.getstate())
  138.  
  139.     
  140.     def randrange(self, start, stop = None, step = 1, int = int, default = None):
  141.         """Choose a random item from range(start, stop[, step]).
  142.  
  143.         This fixes the problem with randint() which includes the
  144.         endpoint; in Python this is usually not what you want.
  145.         Do not supply the 'int' and 'default' arguments.
  146.         """
  147.         istart = int(start)
  148.         if istart != start:
  149.             raise ValueError, 'non-integer arg 1 for randrange()'
  150.         
  151.         if stop is default:
  152.             if istart > 0:
  153.                 return int(self.random() * istart)
  154.             
  155.             raise ValueError, 'empty range for randrange()'
  156.         
  157.         istop = int(stop)
  158.         if istop != stop:
  159.             raise ValueError, 'non-integer stop for randrange()'
  160.         
  161.         if step == 1 and istart < istop:
  162.             return int(istart + int(self.random() * (istop - istart)))
  163.         
  164.         if step == 1:
  165.             raise ValueError, 'empty range for randrange()'
  166.         
  167.         istep = int(step)
  168.         if istep != step:
  169.             raise ValueError, 'non-integer step for randrange()'
  170.         
  171.         if istep > 0:
  172.             n = ((istop - istart) + istep - 1) / istep
  173.         elif istep < 0:
  174.             n = ((istop - istart) + istep + 1) / istep
  175.         else:
  176.             raise ValueError, 'zero step for randrange()'
  177.         if n <= 0:
  178.             raise ValueError, 'empty range for randrange()'
  179.         
  180.         return istart + istep * int(self.random() * n)
  181.  
  182.     
  183.     def randint(self, a, b):
  184.         '''Return random integer in range [a, b], including both end points.
  185.         '''
  186.         return self.randrange(a, b + 1)
  187.  
  188.     
  189.     def choice(self, seq):
  190.         '''Choose a random element from a non-empty sequence.'''
  191.         return seq[int(self.random() * len(seq))]
  192.  
  193.     
  194.     def shuffle(self, x, random = None, int = int):
  195.         '''x, random=random.random -> shuffle list x in place; return None.
  196.  
  197.         Optional arg random is a 0-argument function returning a random
  198.         float in [0.0, 1.0); by default, the standard random.random.
  199.  
  200.         Note that for even rather small len(x), the total number of
  201.         permutations of x is larger than the period of most random number
  202.         generators; this implies that "most" permutations of a long
  203.         sequence can never be generated.
  204.         '''
  205.         if random is None:
  206.             random = self.random
  207.         
  208.         for i in xrange(len(x) - 1, 0, -1):
  209.             j = int(random() * (i + 1))
  210.             (x[i], x[j]) = (x[j], x[i])
  211.         
  212.  
  213.     
  214.     def sample(self, population, k):
  215.         '''Chooses k unique random elements from a population sequence.
  216.  
  217.         Returns a new list containing elements from the population while
  218.         leaving the original population unchanged.  The resulting list is
  219.         in selection order so that all sub-slices will also be valid random
  220.         samples.  This allows raffle winners (the sample) to be partitioned
  221.         into grand prize and second place winners (the subslices).
  222.  
  223.         Members of the population need not be hashable or unique.  If the
  224.         population contains repeats, then each occurrence is a possible
  225.         selection in the sample.
  226.  
  227.         To choose a sample in a range of integers, use xrange as an argument.
  228.         This is especially fast and space efficient for sampling from a
  229.         large population:   sample(xrange(10000000), 60)
  230.         '''
  231.         n = len(population)
  232.         if not None if k <= k else k <= n:
  233.             raise ValueError, 'sample larger than population'
  234.         
  235.         random = self.random
  236.         _int = int
  237.         result = [
  238.             None] * k
  239.         if n < 6 * k:
  240.             pool = list(population)
  241.             for i in xrange(k):
  242.                 j = _int(random() * (n - i))
  243.                 result[i] = pool[j]
  244.                 pool[j] = pool[n - i - 1]
  245.             
  246.         else:
  247.             selected = { }
  248.             for i in xrange(k):
  249.                 j = _int(random() * n)
  250.                 while j in selected:
  251.                     j = _int(random() * n)
  252.                 result[i] = selected[j] = population[j]
  253.             
  254.         return result
  255.  
  256.     
  257.     def uniform(self, a, b):
  258.         '''Get a random number in the range [a, b).'''
  259.         return a + (b - a) * self.random()
  260.  
  261.     
  262.     def normalvariate(self, mu, sigma):
  263.         '''Normal distribution.
  264.  
  265.         mu is the mean, and sigma is the standard deviation.
  266.  
  267.         '''
  268.         random = self.random
  269.         while True:
  270.             u1 = random()
  271.             u2 = 1.0 - random()
  272.             z = NV_MAGICCONST * (u1 - 0.5) / u2
  273.             zz = z * z / 4.0
  274.             if zz <= -_log(u2):
  275.                 break
  276.                 continue
  277.         return mu + z * sigma
  278.  
  279.     
  280.     def lognormvariate(self, mu, sigma):
  281.         """Log normal distribution.
  282.  
  283.         If you take the natural logarithm of this distribution, you'll get a
  284.         normal distribution with mean mu and standard deviation sigma.
  285.         mu can have any value, and sigma must be greater than zero.
  286.  
  287.         """
  288.         return _exp(self.normalvariate(mu, sigma))
  289.  
  290.     
  291.     def cunifvariate(self, mean, arc):
  292.         '''Circular uniform distribution.
  293.  
  294.         mean is the mean angle, and arc is the range of the distribution,
  295.         centered around the mean angle.  Both values must be expressed in
  296.         radians.  Returned values range between mean - arc/2 and
  297.         mean + arc/2 and are normalized to between 0 and pi.
  298.  
  299.         Deprecated in version 2.3.  Use:
  300.             (mean + arc * (Random.random() - 0.5)) % Math.pi
  301.  
  302.         '''
  303.         import warnings
  304.         warnings.warn('The cunifvariate function is deprecated; Use (mean + arc * (Random.random() - 0.5)) % Math.pi instead', DeprecationWarning)
  305.         return (mean + arc * (self.random() - 0.5)) % _pi
  306.  
  307.     
  308.     def expovariate(self, lambd):
  309.         '''Exponential distribution.
  310.  
  311.         lambd is 1.0 divided by the desired mean.  (The parameter would be
  312.         called "lambda", but that is a reserved word in Python.)  Returned
  313.         values range from 0 to positive infinity.
  314.  
  315.         '''
  316.         random = self.random
  317.         u = random()
  318.         while u <= 9.9999999999999995e-08:
  319.             u = random()
  320.         return -_log(u) / lambd
  321.  
  322.     
  323.     def vonmisesvariate(self, mu, kappa):
  324.         '''Circular data distribution.
  325.  
  326.         mu is the mean angle, expressed in radians between 0 and 2*pi, and
  327.         kappa is the concentration parameter, which must be greater than or
  328.         equal to zero.  If kappa is equal to zero, this distribution reduces
  329.         to a uniform random angle over the range 0 to 2*pi.
  330.  
  331.         '''
  332.         random = self.random
  333.         if kappa <= 9.9999999999999995e-07:
  334.             return TWOPI * random()
  335.         
  336.         a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa)
  337.         b = (a - _sqrt(2.0 * a)) / (2.0 * kappa)
  338.         r = (1.0 + b * b) / (2.0 * b)
  339.         while True:
  340.             u1 = random()
  341.             z = _cos(_pi * u1)
  342.             f = (1.0 + r * z) / (r + z)
  343.             c = kappa * (r - f)
  344.             u2 = random()
  345.             if u2 >= c * (2.0 - c):
  346.                 pass
  347.             if not (u2 > c * _exp(1.0 - c)):
  348.                 break
  349.                 continue
  350.         u3 = random()
  351.         if u3 > 0.5:
  352.             theta = mu % TWOPI + _acos(f)
  353.         else:
  354.             theta = mu % TWOPI - _acos(f)
  355.         return theta
  356.  
  357.     
  358.     def gammavariate(self, alpha, beta):
  359.         '''Gamma distribution.  Not the gamma function!
  360.  
  361.         Conditions on the parameters are alpha > 0 and beta > 0.
  362.  
  363.         '''
  364.         if alpha <= 0.0 or beta <= 0.0:
  365.             raise ValueError, 'gammavariate: alpha and beta must be > 0.0'
  366.         
  367.         random = self.random
  368.         if alpha > 1.0:
  369.             ainv = _sqrt(2.0 * alpha - 1.0)
  370.             bbb = alpha - LOG4
  371.             ccc = alpha + ainv
  372.             while True:
  373.                 u1 = random()
  374.                 if not None if u1 < u1 else u1 < 0.99999990000000005:
  375.                     continue
  376.                 
  377.                 u2 = 1.0 - random()
  378.                 v = _log(u1 / (1.0 - u1)) / ainv
  379.                 x = alpha * _exp(v)
  380.                 z = u1 * u1 * u2
  381.                 r = bbb + ccc * v - x
  382.                 if r + SG_MAGICCONST - 4.5 * z >= 0.0 or r >= _log(z):
  383.                     return x * beta
  384.                     continue
  385.         elif alpha == 1.0:
  386.             u = random()
  387.             while u <= 9.9999999999999995e-08:
  388.                 u = random()
  389.             return -_log(u) * beta
  390.         else:
  391.             while True:
  392.                 u = random()
  393.                 b = (_e + alpha) / _e
  394.                 p = b * u
  395.                 if p <= 1.0:
  396.                     x = pow(p, 1.0 / alpha)
  397.                 else:
  398.                     x = -_log((b - p) / alpha)
  399.                 u1 = random()
  400.                 if p <= 1.0 and u1 > _exp(-x) and p > 1:
  401.                     pass
  402.                 if not (u1 > pow(x, alpha - 1.0)):
  403.                     break
  404.                     continue
  405.             return x * beta
  406.  
  407.     
  408.     def stdgamma(self, alpha, ainv, bbb, ccc):
  409.         import warnings
  410.         warnings.warn('The stdgamma function is deprecated; use gammavariate() instead', DeprecationWarning)
  411.         return self.gammavariate(alpha, 1.0)
  412.  
  413.     
  414.     def gauss(self, mu, sigma):
  415.         '''Gaussian distribution.
  416.  
  417.         mu is the mean, and sigma is the standard deviation.  This is
  418.         slightly faster than the normalvariate() function.
  419.  
  420.         Not thread-safe without a lock around calls.
  421.  
  422.         '''
  423.         random = self.random
  424.         z = self.gauss_next
  425.         self.gauss_next = None
  426.         if z is None:
  427.             x2pi = random() * TWOPI
  428.             g2rad = _sqrt(-2.0 * _log(1.0 - random()))
  429.             z = _cos(x2pi) * g2rad
  430.             self.gauss_next = _sin(x2pi) * g2rad
  431.         
  432.         return mu + z * sigma
  433.  
  434.     
  435.     def betavariate(self, alpha, beta):
  436.         '''Beta distribution.
  437.  
  438.         Conditions on the parameters are alpha > -1 and beta} > -1.
  439.         Returned values range between 0 and 1.
  440.  
  441.         '''
  442.         y = self.gammavariate(alpha, 1.0)
  443.         if y == 0:
  444.             return 0.0
  445.         else:
  446.             return y / (y + self.gammavariate(beta, 1.0))
  447.  
  448.     
  449.     def paretovariate(self, alpha):
  450.         '''Pareto distribution.  alpha is the shape parameter.'''
  451.         u = 1.0 - self.random()
  452.         return 1.0 / pow(u, 1.0 / alpha)
  453.  
  454.     
  455.     def weibullvariate(self, alpha, beta):
  456.         '''Weibull distribution.
  457.  
  458.         alpha is the scale parameter and beta is the shape parameter.
  459.  
  460.         '''
  461.         u = 1.0 - self.random()
  462.         return alpha * pow(-_log(u), 1.0 / beta)
  463.  
  464.  
  465.  
  466. class WichmannHill(Random):
  467.     VERSION = 1
  468.     
  469.     def seed(self, a = None):
  470.         '''Initialize internal state from hashable object.
  471.  
  472.         None or no argument seeds from current time.
  473.  
  474.         If a is not None or an int or long, hash(a) is used instead.
  475.  
  476.         If a is an int or long, a is used directly.  Distinct values between
  477.         0 and 27814431486575L inclusive are guaranteed to yield distinct
  478.         internal states (this guarantee is specific to the default
  479.         Wichmann-Hill generator).
  480.         '''
  481.         if a is None:
  482.             import time
  483.             a = long(time.time() * 256)
  484.         
  485.         if not isinstance(a, (int, long)):
  486.             a = hash(a)
  487.         
  488.         (a, x) = divmod(a, 30268)
  489.         (a, y) = divmod(a, 30306)
  490.         (a, z) = divmod(a, 30322)
  491.         self._seed = (int(x) + 1, int(y) + 1, int(z) + 1)
  492.         self.gauss_next = None
  493.  
  494.     
  495.     def random(self):
  496.         '''Get the next random number in the range [0.0, 1.0).'''
  497.         (x, y, z) = self._seed
  498.         x = 171 * x % 30269
  499.         y = 172 * y % 30307
  500.         z = 170 * z % 30323
  501.         self._seed = (x, y, z)
  502.         return (x / 30269.0 + y / 30307.0 + z / 30323.0) % 1.0
  503.  
  504.     
  505.     def getstate(self):
  506.         '''Return internal state; can be passed to setstate() later.'''
  507.         return (self.VERSION, self._seed, self.gauss_next)
  508.  
  509.     
  510.     def setstate(self, state):
  511.         '''Restore internal state from object returned by getstate().'''
  512.         version = state[0]
  513.         if version == 1:
  514.             (version, self._seed, self.gauss_next) = state
  515.         else:
  516.             raise ValueError('state with version %s passed to Random.setstate() of version %s' % (version, self.VERSION))
  517.  
  518.     
  519.     def jumpahead(self, n):
  520.         '''Act as if n calls to random() were made, but quickly.
  521.  
  522.         n is an int, greater than or equal to 0.
  523.  
  524.         Example use:  If you have 2 threads and know that each will
  525.         consume no more than a million random numbers, create two Random
  526.         objects r1 and r2, then do
  527.             r2.setstate(r1.getstate())
  528.             r2.jumpahead(1000000)
  529.         Then r1 and r2 will use guaranteed-disjoint segments of the full
  530.         period.
  531.         '''
  532.         if not (n >= 0):
  533.             raise ValueError('n must be >= 0')
  534.         
  535.         (x, y, z) = self._seed
  536.         x = int(x * pow(171, n, 30269)) % 30269
  537.         y = int(y * pow(172, n, 30307)) % 30307
  538.         z = int(z * pow(170, n, 30323)) % 30323
  539.         self._seed = (x, y, z)
  540.  
  541.     
  542.     def __whseed(self, x = 0, y = 0, z = 0):
  543.         '''Set the Wichmann-Hill seed from (x, y, z).
  544.  
  545.         These must be integers in the range [0, 256).
  546.         '''
  547.         if not None if type(y) == type(y) and type(z) == type(z) else type(z) == int:
  548.             raise TypeError('seeds must be integers')
  549.         
  550.         if x <= x:
  551.             pass
  552.         elif x < 256:
  553.             if y <= y:
  554.                 pass
  555.             elif y < 256:
  556.                 pass
  557.         if not None if z <= z else z < 256:
  558.             raise ValueError('seeds must be in range(0, 256)')
  559.         
  560.         if x == x and y == y:
  561.             pass
  562.         elif y == z:
  563.             import time
  564.             t = long(time.time() * 256)
  565.             t = int(t & 16777215 ^ t >> 24)
  566.             (t, x) = divmod(t, 256)
  567.             (t, y) = divmod(t, 256)
  568.             (t, z) = divmod(t, 256)
  569.         
  570.         if not x:
  571.             pass
  572.         if not y:
  573.             pass
  574.         if not z:
  575.             pass
  576.         self._seed = (1, 1, 1)
  577.         self.gauss_next = None
  578.  
  579.     
  580.     def whseed(self, a = None):
  581.         """Seed from hashable object's hash code.
  582.  
  583.         None or no argument seeds from current time.  It is not guaranteed
  584.         that objects with distinct hash codes lead to distinct internal
  585.         states.
  586.  
  587.         This is obsolete, provided for compatibility with the seed routine
  588.         used prior to Python 2.1.  Use the .seed() method instead.
  589.         """
  590.         if a is None:
  591.             self._WichmannHill__whseed()
  592.             return None
  593.         
  594.         a = hash(a)
  595.         (a, x) = divmod(a, 256)
  596.         (a, y) = divmod(a, 256)
  597.         (a, z) = divmod(a, 256)
  598.         if not (x + a) % 256:
  599.             pass
  600.         x = 1
  601.         if not (y + a) % 256:
  602.             pass
  603.         y = 1
  604.         if not (z + a) % 256:
  605.             pass
  606.         z = 1
  607.         self._WichmannHill__whseed(x, y, z)
  608.  
  609.  
  610.  
  611. def _test_generator(n, funccall):
  612.     import time
  613.     print n, 'times', funccall
  614.     code = compile(funccall, funccall, 'eval')
  615.     total = 0.0
  616.     sqsum = 0.0
  617.     smallest = 10000000000.0
  618.     largest = -10000000000.0
  619.     t0 = time.time()
  620.     for i in range(n):
  621.         x = eval(code)
  622.         total += x
  623.         sqsum = sqsum + x * x
  624.         smallest = min(x, smallest)
  625.         largest = max(x, largest)
  626.     
  627.     t1 = time.time()
  628.     print round(t1 - t0, 3), 'sec,',
  629.     avg = total / n
  630.     stddev = _sqrt(sqsum / n - avg * avg)
  631.     print 'avg %g, stddev %g, min %g, max %g' % (avg, stddev, smallest, largest)
  632.  
  633.  
  634. def _test(N = 2000):
  635.     _test_generator(N, 'random()')
  636.     _test_generator(N, 'normalvariate(0.0, 1.0)')
  637.     _test_generator(N, 'lognormvariate(0.0, 1.0)')
  638.     _test_generator(N, 'cunifvariate(0.0, 1.0)')
  639.     _test_generator(N, 'vonmisesvariate(0.0, 1.0)')
  640.     _test_generator(N, 'gammavariate(0.01, 1.0)')
  641.     _test_generator(N, 'gammavariate(0.1, 1.0)')
  642.     _test_generator(N, 'gammavariate(0.1, 2.0)')
  643.     _test_generator(N, 'gammavariate(0.5, 1.0)')
  644.     _test_generator(N, 'gammavariate(0.9, 1.0)')
  645.     _test_generator(N, 'gammavariate(1.0, 1.0)')
  646.     _test_generator(N, 'gammavariate(2.0, 1.0)')
  647.     _test_generator(N, 'gammavariate(20.0, 1.0)')
  648.     _test_generator(N, 'gammavariate(200.0, 1.0)')
  649.     _test_generator(N, 'gauss(0.0, 1.0)')
  650.     _test_generator(N, 'betavariate(3.0, 3.0)')
  651.  
  652. _inst = Random()
  653. seed = _inst.seed
  654. random = _inst.random
  655. uniform = _inst.uniform
  656. randint = _inst.randint
  657. choice = _inst.choice
  658. randrange = _inst.randrange
  659. sample = _inst.sample
  660. shuffle = _inst.shuffle
  661. normalvariate = _inst.normalvariate
  662. lognormvariate = _inst.lognormvariate
  663. cunifvariate = _inst.cunifvariate
  664. expovariate = _inst.expovariate
  665. vonmisesvariate = _inst.vonmisesvariate
  666. gammavariate = _inst.gammavariate
  667. stdgamma = _inst.stdgamma
  668. gauss = _inst.gauss
  669. betavariate = _inst.betavariate
  670. paretovariate = _inst.paretovariate
  671. weibullvariate = _inst.weibullvariate
  672. getstate = _inst.getstate
  673. setstate = _inst.setstate
  674. jumpahead = _inst.jumpahead
  675. if __name__ == '__main__':
  676.     _test()
  677.  
  678.